package de.jmda.gen.java.impl;

import java.util.LinkedList;
import java.util.List;

import de.jmda.gen.Generator;
import de.jmda.gen.impl.AbstractCompoundGenerator;
import de.jmda.gen.java.AnnotationStatementGenerator;
import de.jmda.gen.java.AnnotationStatementsGenerator;
import de.jmda.gen.java.DeclarationGenerator;
import de.jmda.gen.java.JavaDocGenerator;

/**
 * Sets component separator to {@link System#lineSeparator()}. Maintains a
 * <ul>
 *   <li>{@link #javaDocGenerator} and an</li>
 *   <li>{@link #annotationStatementsGenerator}.</li>
 * </ul>
 *
 * @author roger.jmda@gmail.com
 */
public abstract class AbstractDeclarationGenerator
		extends AbstractCompoundGenerator
		implements DeclarationGenerator
{
	private JavaDocGenerator javaDocGenerator;
	private AnnotationStatementsGenerator annotationStatementsGenerator;

	/**
	 * Sets separator for component generation process to {@link
	 * System#lineSeparator()}.
	 * 
	 * @see #getGeneratorComponents()
	 * @see #generate()
	 * @see #setPartsSeparator(String)
	 */
	public AbstractDeclarationGenerator()
	{
		super();
		setComponentSeparator(System.lineSeparator());
	}

	/**
	 * @return collection of <code>Generator</code>s with the return values of the
	 *         following methods in the following order:
	 *         <ul>
	 *           <li>{@link #getDocumentationGenerator()}</li>
	 *           <li>{@link #getAnnotationStatementsGenerator()}</li>
	 *           <li>{@link #getDeclaredElementGenerator()}</li>
	 *         </ul>
	 * 
	 * @see de.jmda.gen.CompoundGenerator#getGeneratorComponents()
	 */
	@Override
  public final List<Generator> getGeneratorComponents()
  {
		List<Generator> result = new LinkedList<Generator>();

		result.add(getJavaDocGenerator());
		result.add(getAnnotationStatementsGenerator());
		result.add(getDeclaredElementGenerator());

	  return result;
  }

	/**
	 * @return {@link #javaDocGenerator}, may be <code>null</code> because
	 *         documentation is optional
	 *
	 * @see de.jmda.gen.java.DeclarationGenerator#getJavaDocGenerator()
	 */
	@Override
	public JavaDocGenerator getJavaDocGenerator()
	{
		return javaDocGenerator;
	}

	@Override
	public void setJavaDocGenerator(JavaDocGenerator javaDocGenerator)
  {
  	this.javaDocGenerator = javaDocGenerator;
  }

	@Override
	public JavaDocGenerator demandJavaDocGenerator()
	{
		if (javaDocGenerator == null)
		{
			javaDocGenerator = new DefaultJavaDocGenerator();
		}
		return javaDocGenerator;
	}

	/**
	 * @return {@link #annotationStatementsGenerator}, may be <code>null</code>
	 *         because annotations are optional (in general)
	 *
	 * @see de.jmda.gen.java.DeclarationGenerator#getAnnotationStatementsGenerator()
	 */
	@Override
	public AnnotationStatementsGenerator getAnnotationStatementsGenerator()
	{
		return annotationStatementsGenerator;
	}

	@Override
	public void setAnnotationStatementsGenerator(
      AnnotationStatementsGenerator annotationStatementsGenerator)
  {
  	this.annotationStatementsGenerator = annotationStatementsGenerator;
  }

	@Override
	public AnnotationStatementsGenerator demandAnnotationStatementsGenerator()
	{
		if (annotationStatementsGenerator == null)
		{
			annotationStatementsGenerator = new DefaultAnnotationStatementsGenerator();
		}
		return annotationStatementsGenerator;
	}

	/**
	 * Convenience method to add an <code>AnnotationStatementGenerator</code> to
	 * <code>AnnotationStatementGenerator</code>s in {@link
	 * #getAnnotationStatementsGenerator()}.
	 *
	 * @param annotationStatementGenerator
	 */
	public void add(AnnotationStatementGenerator annotationStatementGenerator)
	{
		getAnnotationStatementsGenerator().getAnnotationStatementGenerators()
		                                  .add(annotationStatementGenerator);
	}
}